export default {
  created() {
    this.getData();
  },
  data() {
    // 自定义校验规则函数
    const checkMobile = function(rule, value, callback) {
      // rule 规则对象，value 当前表单元素的值，callback 校验完毕后的回调函数（返回值 成功/失败）
      // 成功 直接调用callback()函数，
      // 失败 在调用callback()函数时需传递一个错误对象（错误对象中要有一个错误信息，这个错误信息将来会显示在表单元素下面，进行提示）callback( new Error("错误信息"))
      // 定义自己的校验规则
      // 是校验组件去调用这个函数，定义的规则要符合校验组件的要求
      if (!/^1[356789]\d{9}$/.test(value)) {
        return callback(new Error("手机号输入格式不正确"));
      }
      callback();
    };
    return {
      // 获取用户列表的参数
      reqParams: {
        query: "",
        pagenum: 1,
        pagesize: 2,
      },
      // 用户列表数据
      usersList: [],
      // 分页相关数据(总页数)
      total: 0,
      // 添加用户对话框相关数据
      addDialogFormVisible: false,
      formLabelWidth: "120px",
      addForm: {
        username: "",
        password: "",
        email: "",
        mobile: "",
      },
      addRules: {
        username: [
          { required: true, message: "用户名必填", trigger: "blur" },
          { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" },
        ],
        password: [
          { required: true, message: "密码必填", trigger: "blur" },
          {
            min: 6,
            max: 18,
            message: "长度在 6 到 18 个字符",
            trigger: "blur",
          },
        ],
        email: [
          { required: true, message: "邮箱必填", trigger: "blur" },
          { type: "email", message: "请输入正确的邮箱地址", trigger: "blur" },
        ],
        mobile: [
          { required: true, message: "手机必填", trigger: "blur" },
          // 没有符合国情的校验规则 使用自定义校验规则
          // { validator: 校验函数名称, trigger: 'blur' }
          // 校验函数应该写在哪里？ 写在methods中是给当前的vue组件调用，我们这个校验函数是给form表单调用，所以不能定义在本身的methods方法中
          // 校验函数应该写在 return之前，因为函数要提前声明才能调用，（因为addRules需要使用所以定义在data中的return之前）
          { validator: checkMobile, trigger: "blur" },
        ],
      },
      // 分配角色对话框相关数据
      roleDialogFormVisible: false,
      roleUserName: "",
      roleUserID: null,
      roleName: "",
      roleList: [],
      roleSelected: "",
      //编辑用户对话框相关数据
      editDialogFormVisible: false,
      editForm: {
        username: "",
        email: "",
        mobile: "",
      },
      editRules: {
        // 失去焦点的时对表单进行校验
        email: [
          { required: true, message: "邮箱必填", trigger: "blur" },
          { type: "email", message: "请输入正确的邮箱地址", trigger: "blur" },
        ],
        mobile: [
          { required: true, message: "手机必填", trigger: "blur" },
          // 没有符合国情的校验规则 使用自定义校验规则
          // { validator: 校验函数名称, trigger: 'blur' }
          // 校验函数应该写在哪里？ 写在methods中是给当前的vue组件调用，我们这个校验函数是给form表单调用，所以不能定义在本身的methods方法中
          // 校验函数应该写在 return之前，因为函数要提前声明才能调用，（因为addRules需要使用所以定义在data中的return之前）
          { validator: checkMobile, trigger: "blur" },
        ],
      },
    };
  },
  methods: {
    async getData() {
      // 获取表格依赖的数据 用户列表数据
      // 后台返回的数据 res = {data :{data:"数据",meta:{status:200,msg:"提示"}}}
      const res = await this.$http.get("users", { params: this.reqParams });
      // console.log(res);
      const {
        data: { data, meta },
      } = res;
      if (meta.status !== 200) {
        return this.$message.error(meta.msg);
      }
      // console.log(data);
      // 修改data中的表格数据 驱动视图改变
      this.usersList = data.users;
      // data.total 是总条数
      // this.total = Math.ceil(data.total / this.reqParams.pagesize); // this.total 是总页数
      this.total = data.total; //this.total 是总条数(完整页码显示的方法)
    },
    search() {
      // 获取输入框的内容 需要携带
      // 使用v-model双向数据绑定 reqParmas.query数据 当输入的内容修改的时候reqParams.query也修改
      this.getData();
    },
    pager(newPagenum) {
      // console.log(newPagenum);
      // 更新请求的参数 reqParams.pagenum 为 newPagenum
      this.reqParams.pagenum = newPagenum;
      // 重新获取数据
      this.getData();
    },
    size(newPagesize) {
      // console.log(newPagesize);
      this.reqParams.pagesize = newPagesize;
      this.getData();
    },
    addUser() {
      // 添加用户
      // 调用 表单组件的函数 函数是挂载在dom元素上的
      this.$refs.addForm.validate(async (valid) => {
        if (valid) {
          // console.log(this.addForm);
          // 进行数据的提交
          const {
            data: { meta },
          } = await this.$http.post("users", this.addForm);
          // console.log(data);
          // console.log(meta);
          // 失败
          if (meta.status !== 201) {
            return this.$message.error(meta.msg);
          }
          // 成功
          this.addDialogFormVisible = false;
          // 最好跳转到第一页
          this.reqParams.pagenum = 1;
          this.getData();
        }
      });
    },
    // 重置添加用户列表（方法一）
    openAddDialog() {
      // 显示对话框
      this.addDialogFormVisible = true;
      // 重置添加表单
      // "TypeError: Cannot read property 'resetFields' of undefined"
      // 因为 addForm 是 undefined 引起以上的错误
      // 当 this.addDialogFormVisible = true 时，需要耗时所以对话框和表单并没有渲染到页面上
      // 因为属于驱动视图 需要渲染的时间,此时获取dom元素，是获取不到dom元素的，因为dom元素还没有渲染到页面
      // 所以 this.$refs.addForm.resetFields() 报以上错误，渲染需要时间，此时还没有获取到addForm
      // 解决方案一：等dom渲染完毕在去获取dom、调用resetFields()函数
      // 1.使用原始方式，setTimeout(fn,0) 等当前函数作用域下所有代码执行完毕后在执行fn中的代码
      // setTimeout(() => {
      //   this.$refs.addForm.resetFields();
      // }, 0);
      // 解决方案二：使用 $nextTick(fn) 等待dom渲染完毕
      // 1.含义： 下一帧 去执行fn函数    浏览器一秒渲染60次  60帧
      this.$nextTick(() => {
        this.$refs.addForm.resetFields();
      });
    },
    // 重置添加用户列表（方法二）
    // addDialogClose() {
    //   this.$refs.addForm.resetFields();
    // },
    // 删除用户
    delUser(id) {
      // 提示弹出框
      this.$confirm("亲，是否删除该用户", "温馨提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(async () => {
          // 需要用户的ID
          // 删除请求
          // 问请求方式有几种8种：
          // 常用的有五种，这是一种resetful接口定义规范：
          // get    查询操作
          // post   添加操作
          // put    修改操作  整个数据修改
          // patch  修改操作  部分属性修改
          // delete 删除操作

          // 确认删除
          // console.log(id);
          // 向后台发送请求删除的数据
          const {
            data: { meta },
          } = await this.$http.delete(`users/${id}`, id);
          // 删除失败情况
          if (meta.status !== 200) {
            return this.$message.error(meta.msg);
          }
          // 删除成功情况
          this.$message({
            type: "success",
            message: "删除成功!",
          });
          this.getData();
        })
        .catch(() => {
          // 取消删除
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
    async toggleState(row) {
      console.log(row);
      // scope.row 对象中就有 {id,mg_state} 状态的切换就是 !row.mg_state
      // 当我们切换状态时，修改当前组件的值，值是双向数据绑定 所有mg_state 已经修改不用取反了
      const {
        data: { meta },
      } = await this.$http.put(`users/${row.id}/state/${row.mg_state}`);
      if (meta.status != 200) return this.$message.error("切换状态失败");
      this.$message.success(meta.msg);
    },
    async openChangeRole(row) {
      console.log(row);
      // 获取 当前行数据
      // 获取 当前角色列表数据
      const {
        data: { data, meta },
      } = await this.$http.get("roles");
      if (meta.status !== 200) {
        return this.$message.error(meta.msg);
      }
      // console.log(data);
      // 两项数据准备完毕 开始渲染
      this.roleUserName = row.username;
      this.roleName = row.role_name;
      this.roleList = data;
      // 目的：用于将来分配角色时使用
      this.roleUserId = row.id;
      // 清除下拉列表内容
      this.roleSelected = "";
      // 显示对话框
      this.roleDialogFormVisible = true;
    },
    async changeRole() {
      //点击确认按钮，修改当前用户角色
      //1.明确修改角色需要哪些数据 用户ID 角色ID
      //2.准备数据 用户ID 在打开对话框的时候 roleUserId赋值
      //3.准备数据 角色ID v-model = "roleSelected" 就是选中的角色ID
      const {
        data: { meta },
      } = await this.$http.put(`users/${this.roleUserId}/role`, {
        rid: this.roleSelected,
      });
      // console.log(meta);
      // 4.分配角色失败 显示提示信息
      if (meta.status !== 200) {
        return this.$message.error("分配角色失败");
      }
      //5.分配角色成功 更新列表
      this.getData();
      this.roleDialogFormVisible = false;
      if (meta.status == 200) {
        return this.$message.success(meta.msg);
      }
    },
    //打开编辑对话框
    openEditDialog(row) {
      //填充表单(通过获取当前行获取数据，没有使用发送请求获取数据)
      //1.获取当前行数据 row
      //2.修改 editForm 表单中的数据
      // console.log(row);
      // this.editForm.id = row.id;
      // this.editForm.username = row.username;
      // this.editForm.email = row.email;
      // this.editForm.mobile = row.mobile;
      this.editDialogFormVisible = true;
      //表单重置 重置表单的状态情况（例如校验提示内容）
      this.$nextTick(() => {
        this.$refs.editForm.resetFields();
        this.editForm.id = row.id;
        this.editForm.username = row.username;
        this.editForm.email = row.email;
        this.editForm.mobile = row.mobile;
      });
    },
    //编辑用户
    editUser() {
      //点击确认按钮 对整个表单进行校验
      //这个校验要通过操作DOM的方式进行校验
      //对整个表单进行校验
      this.$refs.editForm.validate(async (valid) => {
        //发数据进行校验 是一个异步操作所以是async
        if (valid) {
          //进行异步操作 编辑用户
          //通过const定义常量，接受请求结果
          const {
            data: { meta },
          } = await this.$http.put(`users/${this.editForm.id}`, {
            email: this.editForm.email,
            mobile: this.editForm.mobile,
          });
          //编辑用户失败
          if (meta.status !== 200) {
            return this.$message.error(meta.msg);
          }
          //编辑用户成功
          //1.关闭编辑用户对话框
          //2.更新数据列表
          this.getData();
          this.editDialogFormVisible = false;
        }
      });
    },
  },
};
